﻿using System;
using System.IO;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Drawing;
using System.Xml;
using System.Xml.Serialization;
using rlTodayMakeSkin.Project.Attributes;
using rlTodayMakeSkin.Project;
using rlTodayMakeSkin.GUI;
using rlTodayMakeSkin.Project.XmlElement.XmlSubElements;


namespace rlTodayMakeSkin.Project.XmlElement
{
    /// <summary>
    /// base class for elements that can be included in the skin.xml file
    /// </summary>
    [Serializable]
    abstract public class rlTodayXmlElement
    {
        protected int intX = -1;
        protected int intY = -1;
        protected int intHeight = 24;
        protected int intWidth = 24;
        protected string strNome;
        protected XmlAttributeCollection listaAtt;
        protected SkinControl guiCtrl;
        protected rlTodayProject myProject;

        public rlTodayXmlElement(XmlAttributeCollection attributi, rlTodayProject prj)
        {
            this.listaAtt = attributi;
            myProject = prj;
            if (listaAtt != null)
            {
                if (listaAtt["x"] != null) intX = int.Parse(listaAtt["x"].Value);
                if (listaAtt["y"] != null) intY = int.Parse(listaAtt["y"].Value);
                /*if (listaAtt["height"] != null) intHeight = int.Parse(listaAtt["height"].Value);
                if (listaAtt["width"] != null) intWidth = int.Parse(listaAtt["width"].Value);*/
            }
        }

         public rlTodayXmlElement() { }//for the serialization

        public rlTodayXmlElement(rlTodayProject p)
        {
            myProject = p;
            listaAtt = null;
        }

        /*Proprietà*/
        /// <summary>
        /// gets the gui control that rapresentes the xml element
        /// </summary>
        public SkinControl GetGuiControl()
        {
            return guiCtrl;
           
        }

        /// <summary>
        /// Gest the project of this element
        /// </summary>
        /// <returns></returns>
        public rlTodayProject GetProject()
        {
            return myProject;
        }

        /// <summary>
        /// sets the gui control that rapresentes the xml element
        /// </summary>
        public void SetGuiControl(SkinControl ctrl)
        {
            guiCtrl = ctrl;
        }

        /// <summary>
        /// Gets, sets x coordinate of the element in the skin
        /// </summary>
        [PropertyDescriptionAttribute("Gets, sets x coordinate of the element in the skin", PropertyTypes.INTEGER)]
        [XmlAttribute("x")]
        public int X
        {
            get { return intX; }
            set { intX = value; }
        }

        /// <summary>
        /// Gets, sets y coordinate of the element in the skin
        /// </summary>
        [PropertyDescriptionAttribute("Gets, sets y coordinate of the element in the skin", PropertyTypes.INTEGER)]
        [XmlAttribute("y")]
        public int Y
        {
            get { return intY; }
            set { intY = value; }
        }

        
        /// <summary>
        /// Gets, sets height of the element in the skin
        /// </summary>
        [PropertyDescriptionAttribute("Gets, sets height of the element in the skin", PropertyTypes.INTEGER, ReadOnlyProperty = true)]
        [XmlIgnore()]
        public int Height
        {
            get { return intHeight; }
            set { intHeight = value;
            guiCtrl.SetHeight(value);
            }
        }

        /// <summary>
        /// Gets, sets width of the element in the skin
        /// </summary>
        [PropertyDescriptionAttribute("Gets, sets width of the element in the skin", PropertyTypes.INTEGER, ReadOnlyProperty = true)]
        [XmlIgnore()]
        public int Width
        {
            get { return intWidth; }
            set { intWidth = value;
                  guiCtrl.SetWidth(value);
            }
        }

        /// <summary>
        /// Gets name of the type of element in the skin.xml
        /// </summary>
        [PropertyDescriptionAttribute("Gets name of the type of element in the skin.xml", ReadOnlyProperty=true)]
        [XmlIgnore()]
        public string Name
        {
            get { return strNome; }
        }

        /// <summary>
        /// Returns a color object from a string that represents its value in rgb form
        /// </summary>
        /// <param name="strRGBValue">a string formatted as RGB(R,G,B) where R,G,B are integer values</param>
        /// <returns></returns>
        public static System.Drawing.Color GetColorFromRGB(string strRGBValue)
        {
            int firstComma = strRGBValue.IndexOf(',');
            int secondComma = strRGBValue.LastIndexOf(',');
            int r = int.Parse(strRGBValue.Substring(4, firstComma - 4));
            int g = int.Parse(strRGBValue.Substring(firstComma + 1, secondComma - firstComma - 1));
            int b = int.Parse(strRGBValue.Substring(secondComma + 1, strRGBValue.Length - secondComma - 2));
            return System.Drawing.Color.FromArgb(r, g, b);
        }

        /// <summary>
        /// Returns a string that represents rgb values of the color in the form
        /// "RGB(R, G, B)"
        /// </summary>
        /// <param name="c">Color of wich returns the RGB value</param>
        /// <returns>a string that represents RGB value of the color</returns>
        public static string GetRGBFromColor(System.Drawing.Color c)
        {
            return "RGB(" +
              c.R + "," +
              c.G + "," +
              c.B + ")";
        }

        /// <summary>
        /// Drawas content of the element in the graphics
        /// </summary>
        /// <param name="g">graphics object in wich draws elmement</param>
        public abstract void DrawElement(Graphics g);


        /// <summary>
        /// Draws specificated image in the control
        /// </summary>
        /// <param name="imageName">relative of full path of the image</param>
        /// <remarks>Update Height and Width element property.
        /// If imageName is only name of an image it will be searched in application Image folder</remarks>
        protected void DrawImage(Graphics g,string imageName)
        {
            //if the image is in project directory then choose it, otherwise search image in Images program directory
            if(File.Exists(myProject.Path + "\\" + imageName)){
                imageName = myProject.Path + "\\" + imageName;
            }else{
                imageName = System.Windows.Forms.Application.StartupPath + @"\Images\" + imageName;
            }
            Image i = Bitmap.FromFile(imageName);
            Height = i.Height;
            Width = i.Width;
            g.DrawImage(i, 0, 0, i.Width, i.Height);
        }

        /// <summary>
        /// Drwas a string in the control
        /// </summary>
        /// <param name="g">Graphics object in wich draw string</param>
        /// <param name="s">string to draw</param>
        /// <param name="font">font with wich draw string</param>
        /// <remarks>draws a white string</remarks>
        public void DrawString(Graphics g, string s, rlFont font)
        {
            g.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceOver;
            DrawString(g, s, font, Color.White);
        }

        /// <summary>
        /// Draws a string in the control
        /// </summary>
        /// <param name="g">Graphics object in wich draw string</param>
        /// <param name="s">string to draw</param>
        /// <param name="font">font with wich draw string</param>
        ///<param name="c">color with wich draw the string</param>
        public void DrawString(Graphics g, string s, rlFont font, Color c)
        {
            Font f = new Font(font.FontName, font.Size, (font.Weight == "bold" ? FontStyle.Bold : FontStyle.Regular));
            SizeF dimension = g.MeasureString(s, f);
            Height = (int)dimension.Height;
            Width = (int)dimension.Width;
            g.DrawString(s, f, new SolidBrush(c), 0, 0);
        }


        /// <summary>
        /// Returns a formatted date
        /// </summary>
        /// <param name="format">format in wich represents the current date</param>
        /// <param name="dt">DateTime of wich returning formatted value</param>
        /// <returns></returns>
        /// <remarks>if format is a non valid form method returns "[date]" text</remarks>
        protected string GetFormattedDate(string format, DateTime dt)
        {
            try
            {
                return dt.ToString(format);
            }
            catch
            {
                return "[date]";
            }
        }

    }
}
